perm filename RUN.DOC[HAL,HE] blob sn#146188 filedate 1975-02-20 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	This is a file intended to reflect the current thinking concerning
C00003 00003	EVENTS
C00006 00004	ASSEMBLER
C00007 00005	DEPROACHES
C00012 00006	GRAPH STRUCTURE RF 1/15/75
C00019 00007	CONDITION MONITORS
C00027 ENDMK
CāŠ—;
This is a file intended to reflect the current thinking concerning
the interpreter and all the routines to which it has access.  This
includes arithmetic routines, servo routines, monitor calls.
Everyone involved is invited to add to this document.  It might be a
good idea, even if you have documented some program internally, to at
least mention where it can be found and very generally what it does. 

EVENTS
1/7/75  BO and RF

The compiler allocates event variables both for user-declared events
and for implicit ones, such as those used to implement on-monitors.
These are one word long.  The following monitor calls are available
for events:

MAKE EVENT
one argument: pointer at event variable.  Monitor will generate a new
event, with a null wait queue and no signals.  The index of this
event in the event table will be stored in the event variable.  

SIGNAL EVENT
one argument: pointer at event variable.  (Bo would prefer the index
which is found therein.) If any processes are waiting on this event,
the first one is awakened successfully.  Its execution will not,
however, preempt that of the signalling process (this is possibly the
wrong decision) unless it is of higher priority.  If thee is no
process on the event queue, a record is kept that the signal came in
(a simple count).  If the event was never created, however, the
signal is a no-op. 

WAIT EVENT
one argument: pointer at event varible.  (...) If no signals ready on
that event, then the waiting process is entered on the event's wait
queue; as soon as there is a signal, it is eaten and the process is
successfully reawakened.  If a destroy event occurs first, or if the
event does not exist, then an unsuccessful reawakening occurs. 

DESTROY EVENT
same old argument ().  This destroys the event.  All pending signals
are eaten.  All waiting processes are unsuccessfully awakened.  This
is commonly done at block exit to all local events.  

Note that there is a problem with old events which have been
destoyed, but someone still has access to their name.  If a new event
should be given the same name later, then confusion may arise.  It
may be necessary for the event variable to have two fields: An index
into the event table, and a unique event number which will never be
reassigned. 
ASSEMBLER

We are currently using PALX, which is not capable of creating relocatable
code, nor can it handle external references.  Another assembler may soon
be available, essentially compatible with PALX, which creates a REL file
which can be then loaded into an absolute core image file, then transfered
across via 11TTY.  This new assembler has most of the macro, etc, facitities
which we need.  It seems also to have handles for multiple program counters.

The import of this is that the compiler should most likely create rel files
in the same style as the loader for this assembler expects.  
DEPROACHES
1/9/75 BES, RF

In order to avoid excessive need for trajectory modification in those
motions which have deproaches, calculated via points or calculated
destinations, we need a less wasteful method of recalculating
deproach points than to always recalculate them before each motion,
since this forces the trajectory modifier to consider these "via"
points to be no longer accurate, thereby necessitating an expensive
call to the joint-angle solver. 

The departure point has another severe problem, because it is
conceivable that a user may move the arm manually between the end of
one motion and the beginning of the next.  The departure point should
really be dependent on the current location of the hand before the
motion actually starts, not the current value of the frame at which
it was to arrive during the previous motion. 

A suggested solution to these problems is a modification to the
graph structure, so that it allow these new features:
.  When a node is marked as valid, it also has a validity time associated
with it.
.  A node can be marked as permanently invalid; whenever its value
is required, it must be recalculated.
.  A node can depend on the hand (or, more generally, on any frame)
yet not be on the dependency list for that hand (or frame).

In order to see if a via point has been changed, and therefore
requires that the trajectory be modified, it does not suffice merely
to see if the via point is currently marked as valid, because it may
have been recalculated to a different value since the modifier last
fixed this trajectory.  Therefore, if it is marked as valid, its
validity number is compared to the validity number in the trajectory
data, and only if they match is no modification necessary at this via
point.  If it is marked valid at a different time, then it is
necessary to go to the expense of extracting joint angles, and
modifying the trajectory. 

The way departure points would be handled is that they would be tied
into the graph stucture, as dependent on the location of the hand. 
They would be marked as permanently invalid, and would not be on the
dependency list of the hand.  During trajectory modification phase,
the current location of the arm would be read, and the joint angles
compared to those expected due to the coefficients of the motion.  If
there is an unacceptable discrepancy, that means that not only is the
arm not where it was planned to be, but that the deproach point is
also wrong.  The modifier would then invoke GETVAL to return a value
for the departure point, and since that point is always invalid, a
new frame value would be calculated.  Each new departure point frame
wlll have associated with it a new validity number.

The same idea can be used for via expressions, the approach point,
and a destination expression, although none of these is dependent on
the actual location of the arm.  These can be in the graph
structure in the normal way; thus they will be marked as invalid only
if some member of the expression has changed.  Once again, the
validity time can prevent mistaken adjudgements of validity. 
GRAPH STRUCTURE RF 1/15/75

Graph structure is used to keep the values of some variables
dependent on the fluctuations in the value of others.  This is used
for attachment, and very likely will be used for calculated
via-points and destinations.  The page on deproaches makes some
demands on the nature of the graph structure; here we will make a few
more. 

The calculator cell of a graph node needs to be able to specify
arbitrary computation on current values.  It is to be expected that a
particular calculator will never be called unless all the values on
which it depends have been discovered to be valid; therefore, it is
unlikely (and hopefully, impossible) for the calculator routine to
itself cause an instantiation of a graph traversing routine.  The
most reasonable idea for specifying the calculation is by means of
interpreter pseudo-code, since a system will already exist to treat
it and to carry out arbitrary calculation thereby, and it will not be
any harder to generate such code during compiltion than to generate
any other computational code.  This means, however, that the
addressing of variables in the calculator cell must be compatible
with that in the interpreter; this scheme is to name each variable by
means of an ordered pair: the lexical level, and the offset in that
level.  This information suffices in the interpreter to find a word
which points to the graph node for that variable.  In order for it to
suffice for the calculator cell as well, it seems necessary to give
tthe calculator a pointer to the stack for the current interpreter.
This is not difficult: every time the routine GETVAL is called, it is
given two arguments: a pointer to a graph node, and a pointer to the
base of the current stack.  This latter suffices to find all
variables accessible to that interpreter.  (It may also need to know
the current lexical level.)

A slightly harder problem is to handle calls to GETVAL arising from
condition monitors.  But these monitors themselves will have to have
access to variables, an therefore will have to be given a pointer to
the current stackbase. 

An alternative to the above suggestons is to have another mode of
addressing, namely absolute, in the interpreter.  This will force the
compiler to have a notion of where all the variables are stored, or
to give each a name, and let a loader fix up all references.  I
really dont know how satisfactory this would be. 

There arises also the question of how graph nodes are to point to
each other, for example, for dependence lists.  Should this also be
through the interpreter addressing scheme, or should it be absolute? 
If the former, then there may be confusion when several parallel
interpreters have caused such addresses to be ambiguous if not in
context of a particular stack pointer.  Would this mean that the
graph node would also need a pointer to the base of its stack, that
is, the interpreter stack where it was declared? 

A completely separate problem has to do with block exit.  It seems
improper to leave a block in which a variable has been declared and
to destroy that variable, if it is still somehow linked into the
graph structure.  Therefore, part of the destruction process must be
to remove it.  How is this accomplished?  Its updater cell can be
discarded.  Every cell pointed to by its dependency list must be made
independent of it as follows: All calculators of each element on the
dependency list must be removed.  If this removes all calculators
from some element, then it should be marked as valid.  All
calculators of the destroyed node can be themselves discarded.  If
any other node in the structure has an updator cell which refers to
the newly destroyed node, then we are out of luck. 

In order to remove calculators and updators, which we have documented
in the upper language, it might be easiest if each calculator and
updater be assigned a unique name by the compiler (I think 2↑16=64k
suffices!), and the removal be by name. 
CONDITION MONITORS
RF 2/20/75

There are four types of condition monitors:
. EVENT type:	ON <event> DO <body>
. SOFT type:	ON <arithmetic condition> DO <body>
. SERVO type:	ON <arm status> DO <body>
. HARD type:	ON <interrupt signal> DO <body>

There are the following operations which refer to condition monitors:
. CREATE:	Cause the test to exist.
. ENABLE:	Activate the test
. DISABLE:	Deactivate the test
. TRIGGER:	Cause the test to succeed
. DESTROY:	At end of block.  Can be like disabling.

Condition monitors are handled by the EVENT mechanism.  For each of
the types listed above, each of the operations is performed as
follows:

. EVENT monitors Enabling is done by entering the monitor on the
event queue for the specified event.  The event itself will have been
created at block entry, so there is no danger that it will not exist.
It is not safe to disable this kind of monitor, because destroying
the event will have side effects on other processes waiting for it. 
There is currently no way to remove a process from an event queue
short of destroying the event.  Triggering the monitor is done by
signaling the event.  This will remove the monitor from the queue, so
it might want to reenable itself.  This is just like the initial
enabling.  Some care must be taken to avoid having multiple copies of
the same monitor; we have decided that only one may exist at a time.
This means that enabling must first check that the monitor is not
enabled.  Destruction of an event monitor happens automatically when
its event is destroyed at the end of the block in which it was
declared.  There is no other way to destroy such a monitor.  Note
that a block is not exited until all monitors are gone; this implies
that the program can hang if there is an event monitor on an event
which is declared in an outer block and which never happens.  When
the monitor is destroyed, that is, the event is destroyed, all
processes waiting on that event, including the event monitor, are
unsuccessfully awakened.  Thus the body can notify its parent that it
is gone, so that the parent can terminate the block. 

. SOFT monitors These are implemented with two processes.  One of
them is scheduled, and continually awakens, checks the condition, and
then either signals the event or reschedules itself.  There is a
unique, compiler-generated event which is used for communication
between this process and the process of the monitor body, which is to
be triggered.  Enabling the monitor is done by beginning the
scheduled part.  The monitor is created at block entry by creating
the event and placing the body on its queue.  The monitor is disabled
by setting a flag telling the scheduled part to stop scheduling
itself.  The monitor is destroyed by destroying the event and by
disabling the monitor.  Thus block exit must not only include code
for the destruction of local events, it must also have code for the
disabling of all local monitors. 

.SERVO monitors These are touch-sensor or force-sensing monitors.
They require that some other process make available some information,
such as the current status of the sensors.  These monitors are also
in two parts.  The scheduled part lives at times in level 7, and no
matter how many processes are interested in the touch sensors, only
one touch sensor driver will be present.  It has a list of all the
events it is to cause on each type of occurrence it can detect (for
each sensor, motion in either direction).  While an arm is active,
information is available on the current force.  If a process wishes
to use this information, it is done in a soft way, not a servo way.
Servo monitors are created when their block is entered, by creating
the event and putting the body on the queue.  Enabling is done by
telling the servo routine responsible for the servo device (like the
touch sensors) what is wanted.  If there is no current servo routine
for this, one will appear, and will last as long as someone is around
waiting for a touch sensor to go off.  Disabling is done by telling
the servo device to remove the event from its list of waiters. 
Destruction requires that the servo is told, and that the event
itself is destroyed. 

.HARD monitors These respond to hardware interrupts.  Creation is
done by creating the event and placing the body on the wait queue.
Enabling is done by adding the event to the list associated with the
interrupt handler.  Disabling is done by removing the event from that
list.  Destruction is done by disabling the monitor and destroying
the event.